<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>OpenMesh: Extending the mesh using traits</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="logo_align.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="rwth_vci_rgb.jpg"/></td>
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">OpenMesh
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('a04342.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Extending the mesh using traits </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>This examples shows:</p>
<ul>
<li>How to extend the behaviour of entities using traits.</li>
</ul>
<p>In the previous tutorial we used attributes and changed the type of the data types <code>Point</code>, <code>Normal</code>, <code>TexCoord</code>, and <code>Color</code>. But we can do even more with traits. We can change the behaviour of the mesh entities <code>Vertex</code>, <code>Face</code>, <code>Edge</code>, and <code>Halfedge</code>.</p>
<p>One goal in the design was a highly customizable data structure. Using the traits technique makes it possible. We pick up the smoother again and show an alternative way to implement it. Now we place the necessary data and the functions in the vertex itself</p>
 <div class="fragment"><div class="line"><span class="keyword">struct </span><a class="code" href="a01881.html">MyTraits</a> : <span class="keyword">public</span> <a class="code" href="a02469.html">OpenMesh::DefaultTraits</a></div><div class="line">{</div><div class="line">  <span class="comment">// store barycenter of neighbors in this member</span></div><div class="line">  <a class="code" href="a04476.html#aa5146d858418fcb93715406a6ce8e30f">VertexTraits</a></div><div class="line">  {</div><div class="line">  <span class="keyword">private</span>:</div><div class="line">    Point  cog_;</div><div class="line">  <span class="keyword">public</span>:</div><div class="line"></div><div class="line">    VertexT() : cog_( Point(0.0f, 0.0f, 0.0f ) ) { }</div><div class="line"></div><div class="line">    <span class="keyword">const</span> Point&amp; cog()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> cog_; }</div><div class="line">    <span class="keywordtype">void</span> set_cog(<span class="keyword">const</span> Point&amp; _p) { cog_ = _p; }</div><div class="line">  };</div></div><!-- fragment --></p>
<p>Note the definition of the vertex entity. We use the supplied define <code>VertexTraits</code> (which resolves in a rather inconvenient template definition). Similary we can use the defines <code>FaceTraits</code>, <code>EdgeTraits</code>, and <code>HalfedgeTraits</code> to extend these entities. Now we enhanced the vertex, with the additional member variable <code>cog_</code>, and the get/set-method pair to access the new member.</p>
<p>As before we compute in a first loop the barycenters for all vertices and store the information at the vertices</p>
<p><div class="fragment"><div class="line">      mesh.data(*v_it).set_cog(cog / valence);</div></div><!-- fragment --></p>
<p>In the second pass we set the new position of each vertex</p>
<p><div class="fragment"><div class="line">        mesh.set_point( *v_it, mesh.data(*v_it).cog());</div></div><!-- fragment --></p>
<p>It looks neat, but on the other hand we can't remove the data anymore as we could do with properties! By using traits one creates a 'static' configuration, which can't be changed during runtime.</p>
<p>The complete source looks like this:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;vector&gt;</span></div><div class="line"><span class="comment">// -------------------- OpenMesh</span></div><div class="line"><span class="preprocessor">#include &lt;OpenMesh/Core/IO/MeshIO.hh&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="a04476.html">OpenMesh/Core/Mesh/Traits.hh</a>&gt;</span></div><div class="line"></div><div class="line"><span class="keyword">struct </span><a class="code" href="a01881.html">MyTraits</a> : <span class="keyword">public</span> <a class="code" href="a02469.html">OpenMesh::DefaultTraits</a></div><div class="line">{</div><div class="line">  <span class="comment">// store barycenter of neighbors in this member</span></div><div class="line">  <a class="code" href="a04476.html#aa5146d858418fcb93715406a6ce8e30f">VertexTraits</a></div><div class="line">  {</div><div class="line">  <span class="keyword">private</span>:</div><div class="line">    Point  cog_;</div><div class="line">  <span class="keyword">public</span>:</div><div class="line"></div><div class="line">    VertexT() : cog_( Point(0.0f, 0.0f, 0.0f ) ) { }</div><div class="line"></div><div class="line">    <span class="keyword">const</span> Point&amp; cog()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> cog_; }</div><div class="line">    <span class="keywordtype">void</span> set_cog(<span class="keyword">const</span> Point&amp; _p) { cog_ = _p; }</div><div class="line">  };</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">typedef</span> <a class="code" href="a02377.html">OpenMesh::TriMesh_ArrayKernelT&lt;MyTraits&gt;</a>  MyMesh;</div><div class="line"><span class="keyword">typedef</span> <a class="code" href="a02377.html">OpenMesh::TriMesh_ArrayKernelT&lt;&gt;</a>          <a class="code" href="a02377.html">MyMesh2</a>;</div><div class="line"></div><div class="line"><span class="comment">// ---------------------------------------------------------------------------</span></div><div class="line"><span class="preprocessor">#define SIZEOF( entity,b ) \</span></div><div class="line"><span class="preprocessor">  std::cout &lt;&lt; _prefix &lt;&lt; &quot;size of &quot; &lt;&lt; #entity &lt;&lt; &quot;: &quot; \</span></div><div class="line"><span class="preprocessor">            &lt;&lt; sizeof( entity ) &lt;&lt; std::endl;          \</span></div><div class="line"><span class="preprocessor">  b += sizeof( entity )</span></div><div class="line"></div><div class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> Mesh&gt; </div><div class="line"><span class="keywordtype">void</span> print_size(<span class="keyword">const</span> std::string&amp; _prefix = <span class="stringliteral">&quot;&quot;</span>)</div><div class="line">{</div><div class="line">  <span class="keywordtype">size_t</span> total=0;</div><div class="line">  SIZEOF(<span class="keyword">typename</span> Mesh::Vertex, total);</div><div class="line">  SIZEOF(<span class="keyword">typename</span> <a class="code" href="a02389.html#a249b0c195a81eeab341f7f73089d157e">Mesh::Halfedge</a>, total);</div><div class="line">  SIZEOF(<span class="keyword">typename</span> <a class="code" href="a02389.html#ab2ccdc42b7b25cf35915d3639fc461b2">Mesh::Edge</a>, total);</div><div class="line">  SIZEOF(<span class="keyword">typename</span> <a class="code" href="a02389.html#a71e1e8eaabeb24eca04237931b4bea26">Mesh::Face</a>, total);</div><div class="line">  std::cout &lt;&lt; _prefix &lt;&lt; <span class="stringliteral">&quot;total: &quot;</span> &lt;&lt; total &lt;&lt; std::endl;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="preprocessor">#undef SIZEOF</span></div><div class="line"><span class="comment">// ---------------------------------------------------------------------------</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> **argv)</div><div class="line">{</div><div class="line">  MyMesh  mesh;</div><div class="line"></div><div class="line">  <span class="comment">// check command line options</span></div><div class="line">  <span class="keywordflow">if</span> (argc &lt; 4 || argc &gt; 5) </div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; <span class="stringliteral">&quot;Usage:  &quot;</span> &lt;&lt; argv[0] &lt;&lt; <span class="stringliteral">&quot; [-s] #iterations infile outfile\n&quot;</span>;</div><div class="line">    exit(1);</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">int</span> idx=2;</div><div class="line"></div><div class="line">  <span class="comment">// display size of entities of the enhanced and the default mesh type</span></div><div class="line">  <span class="comment">// when commandline option &#39;-s&#39; has been used.</span></div><div class="line">  <span class="keywordflow">if</span> (argc == 5)</div><div class="line">  {</div><div class="line">    <span class="keywordflow">if</span> (std::string(<span class="stringliteral">&quot;-s&quot;</span>)==argv[idx-1])</div><div class="line">    {</div><div class="line">      std::cout &lt;&lt; <span class="stringliteral">&quot;Enhanced mesh size statistics\n&quot;</span>;</div><div class="line">      print_size&lt;MyMesh&gt;(<span class="stringliteral">&quot;  &quot;</span>);</div><div class="line">      </div><div class="line">      std::cout &lt;&lt; <span class="stringliteral">&quot;Default mesh size statistics\n&quot;</span>;</div><div class="line">      print_size&lt;MyMesh2&gt;(<span class="stringliteral">&quot;  &quot;</span>);</div><div class="line">    }</div><div class="line">    <span class="comment">// else ignore!</span></div><div class="line">    ++idx;</div><div class="line">  }</div><div class="line"></div><div class="line"></div><div class="line">  <span class="comment">// read mesh from stdin</span></div><div class="line">  std::cout&lt;&lt; <span class="stringliteral">&quot; Input mesh: &quot;</span> &lt;&lt; argv[idx] &lt;&lt; std::endl;</div><div class="line">  <span class="keywordflow">if</span> ( ! <a class="code" href="a01236.html#ac417960ec28ffdd7e7003a2b1ebb2d1c">OpenMesh::IO::read_mesh</a>(mesh, argv[idx]) )</div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; <span class="stringliteral">&quot;Error: Cannot read mesh from &quot;</span> &lt;&lt; argv[idx] &lt;&lt; std::endl;</div><div class="line">    <span class="keywordflow">return</span> 0;</div><div class="line">  }</div><div class="line"></div><div class="line"></div><div class="line"></div><div class="line">  <span class="comment">// smoothing mesh argv[1] times</span></div><div class="line">  MyMesh::VertexIter          v_it, v_end(mesh.vertices_end());</div><div class="line">  <a class="code" href="a02389.html#adc7d422e2ce13141e8291f7d29f7ecef">MyMesh::VertexVertexIter</a>    vv_it;</div><div class="line">  <a class="code" href="a02389.html#aed10fb4dfb536b53a5e20c8f2442eadf">MyMesh::Point</a>               cog;</div><div class="line">  <a class="code" href="a02389.html#a15372f27edf521d8e9028e2abccae342">MyMesh::Scalar</a>              valence;</div><div class="line">  <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>                i, N(atoi(argv[idx-1]));</div><div class="line"></div><div class="line">  std::cout&lt;&lt; <span class="stringliteral">&quot;Smooth mesh &quot;</span> &lt;&lt; N &lt;&lt; <span class="stringliteral">&quot; times\n&quot;</span>;</div><div class="line"></div><div class="line">  <span class="keywordflow">for</span> (i=0; i &lt; N; ++i)</div><div class="line">  {</div><div class="line">    <span class="keywordflow">for</span> (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)</div><div class="line">    {</div><div class="line">      cog[0] = cog[1] = cog[2] = valence = 0.0;</div><div class="line">      </div><div class="line">      <span class="keywordflow">for</span> (vv_it=mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)</div><div class="line">      {</div><div class="line">        cog += mesh.point( *vv_it );</div><div class="line">        ++valence;</div><div class="line">      }</div><div class="line"></div><div class="line">      mesh.data(*v_it).set_cog(cog / valence);</div><div class="line">    }</div><div class="line">    </div><div class="line">    <span class="keywordflow">for</span> (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)</div><div class="line">      <span class="keywordflow">if</span> (!mesh.is_boundary(*v_it))</div><div class="line">        mesh.set_point( *v_it, mesh.data(*v_it).cog());</div><div class="line">  }</div><div class="line"></div><div class="line"></div><div class="line">  <span class="comment">// write mesh to stdout</span></div><div class="line">  std::cout&lt;&lt; <span class="stringliteral">&quot;Output mesh: &quot;</span> &lt;&lt; argv[idx+1] &lt;&lt; std::endl;</div><div class="line"></div><div class="line">  <span class="keywordflow">if</span> ( ! <a class="code" href="a01236.html#a18286a792ebf896872f5e26182fc5c7b">OpenMesh::IO::write_mesh</a>(mesh, argv[idx+1]) )</div><div class="line">  {</div><div class="line">      std::cerr &lt;&lt; <span class="stringliteral">&quot;Error: cannot write mesh to &quot;</span> &lt;&lt; argv[idx+1] &lt;&lt; std::endl;</div><div class="line">      <span class="keywordflow">return</span> 0;</div><div class="line">  }</div><div class="line">  <span class="keywordflow">return</span> 1;</div><div class="line">}</div></div><!-- fragment --> </div></div><!-- contents -->
</div><!-- doc-content -->
<hr>
<address>
<small>
<a href="http://www.rwth-graphics.de" style="text-decoration:none;">
</a>
Project <b>OpenMesh</b>, 
&copy;&nbsp; Computer Graphics Group, RWTH Aachen.
Documentation generated using 
<a class="el" href="http://www.doxygen.org/index.html">
<b>doxygen</b>
</a>.
</small>
</address>
</body>
</html>
